﻿namespace MicroCloud.Database
{
    /// <summary>
    /// 数据库对象处理器
    /// </summary>
    public abstract class DataBaseHandler : IDataBaseHandler
    {
        /// <summary>
        /// 初始化一个数据库对象处理器 <see cref="DataBaseHandler"/> 的新实例
        /// </summary>
        /// <param name="serviceProvider">服务提供者</param>
        protected DataBaseHandler(IServiceProvider serviceProvider)
        {
            ServiceProvider = serviceProvider;
        }

        #region 属性
        /// <summary>
        /// 获取 服务提供者对象
        /// </summary>
        protected IServiceProvider ServiceProvider { get; }

        /// <summary>
        /// 获取 日志对象
        /// </summary>
        protected ILogger Logger => ServiceProvider.GetLogger(GetType());

        /// <summary>
        /// 获取 初始化的顺序编号
        /// </summary>
        public virtual decimal OrderNo => 0;

        /// <summary>
        /// 获取 是否应用所有的数据上下文
        /// <para>默认 false，如果为 true，则忽略 DbContextTypes 属性。</para>
        /// </summary>
        public virtual bool AllDbContext => false;

        /// <summary>
        /// 获取 所属的数据上下文类型集合
        /// <para>如集合为空且 AllDbContext 为 false 时，将使用默认上下文，否则使用指定类型的上下文类型。</para>
        /// </summary>
        public virtual Type[] DbContextTypes { get; private set; } = Array.Empty<Type>();

        /// <summary>
        /// 获取 是否删除
        /// <para>默认 false，如果为 true，则执行删除操作。</para>
        /// </summary>
        public virtual bool Deleted => false;

        /// <summary>
        /// 获取 数据上下文的配置信息
        /// </summary>
        public Dictionary<Type, DbContextOption> DbContextOptions
        {
            get
            {
               var dbContextOptions = new Dictionary<Type, DbContextOption>();
                // 执行<see cref="ServiceLifetime.Scoped"/>生命周期的业务逻辑
                ServiceProvider.ExecuteScopedWork(provider =>
                {
                    var unitOfWork = provider.GetUnitOfWork();
                    if (AllDbContext)
                    {
                        DbContextTypes = unitOfWork.GetAllDbContexts().Select(x => x.GetType()).ToArray();
                    }
                    else
                    {
                        DbContextTypes ??= Array.Empty<Type>();
                    }
                    var options = ServiceProvider.GetMicroCloudOptions();
                    foreach (var dbContextType in DbContextTypes)
                    {
                        dbContextOptions.Add(dbContextType, options.GetDbContextOptions(dbContextType));
                    }
                });

                return dbContextOptions;
            }
        }

        /// <summary>
        /// 获取 名称
        /// </summary>
        public Dictionary<DatabaseType, string> Names
        {
            get
            {
                var dict = new Dictionary<DatabaseType, string>();
                DatabaseType databaseType = DatabaseType.SqlServer;
                var databaseTypes = databaseType.ToList();
                foreach (var dbType in databaseTypes)
                {
                    dict.Add((DatabaseType)dbType.Value, GetName(DatabaseType.SqlServer));
                }
                return dict;
            }
        }

        /// <summary>
        /// 获取 是否存在脚本
        /// </summary>
        public Dictionary<DatabaseType, string> ExistScripts
        {
            get
            {
                var dict = new Dictionary<DatabaseType, string>();
                DatabaseType databaseType = DatabaseType.SqlServer;
                var databaseTypes = databaseType.ToList();
                foreach (var dbType in databaseTypes)
                {
                    dict.Add((DatabaseType)dbType.Value, GetExistScript(DatabaseType.SqlServer));
                }
                return dict;
            }
        }

        /// <summary>
        /// 获取 创建脚本
        /// </summary>
        public Dictionary<DatabaseType, string> CreateScripts
        {
            get
            {
                var dict = new Dictionary<DatabaseType, string>();
                DatabaseType databaseType = DatabaseType.SqlServer;
                var databaseTypes = databaseType.ToList();
                foreach (var dbType in databaseTypes)
                {
                    dict.Add((DatabaseType)dbType.Value, GetCreateScript(DatabaseType.SqlServer));
                }
                return dict;
            }
        }

        /// <summary>
        /// 获取 更新脚本
        /// </summary>
        public Dictionary<DatabaseType, string> UpdateScripts
        {
            get
            {
                var dict = new Dictionary<DatabaseType, string>();
                DatabaseType databaseType = DatabaseType.SqlServer;
                var databaseTypes = databaseType.ToList();
                foreach (var dbType in databaseTypes)
                {
                    dict.Add((DatabaseType)dbType.Value, GetUpdateScript(DatabaseType.SqlServer));
                }
                return dict;
            }
        }

        /// <summary>
        /// 获取 删除脚本
        /// </summary>
        public Dictionary<DatabaseType, string> DeleteScripts
        {
            get
            {
                var dict = new Dictionary<DatabaseType, string>();
                DatabaseType databaseType = DatabaseType.SqlServer;
                var databaseTypes = databaseType.ToList();
                foreach (var dbType in databaseTypes)
                {
                    dict.Add((DatabaseType)dbType.Value, GetDeleteScript(DatabaseType.SqlServer));
                }
                return dict;
            }
        }
        #endregion

        #region 方法
        /// <summary>
        /// 获取指定数据上下文的上下文配置信息
        /// </summary>
        /// <param name="dbContext">数据上下文</param>
        /// <returns>数据上下文配置信息</returns>
        protected DbContextOption GetDbContextOptions(IDbContext dbContext)
        {
            var dbContextOptions = ServiceProvider.GetMicroCloudOptions().GetDbContextOptions(dbContext);
            return dbContextOptions;
        }

        #region 抽象方法
        /// <summary>
        /// 获取名称
        /// </summary>
        /// <param name="databaseType">数据库类型</param>
        protected abstract string GetName(DatabaseType databaseType);

        /// <summary>
        /// 获取是否存在脚本
        /// </summary>
        /// <param name="databaseType">数据库类型</param>
        protected abstract string GetExistScript(DatabaseType databaseType);

        /// <summary>
        /// 获取创建脚本
        /// </summary>
        /// <param name="databaseType">数据库类型</param>
        protected abstract string GetCreateScript(DatabaseType databaseType);
        
        /// <summary>
        /// 获取更新脚本
        /// </summary>
        /// <param name="databaseType">数据库类型</param>
        protected abstract string GetUpdateScript(DatabaseType databaseType);

        /// <summary>
        /// 获取删除脚本
        /// </summary>
        /// <param name="databaseType">数据库类型</param>
        protected abstract string GetDeleteScript(DatabaseType databaseType);

        #endregion

        #endregion
    }
}